﻿using System;
using System.Collections;
using System.Collections.Specialized;
using System.Web;
using Microsoft.Practices.CompositeWeb;
using Microsoft.Practices.CompositeWeb.Interfaces;
using System.Xml;
using System.Text;
using System.Text.RegularExpressions;

namespace Sitemap.Extensions.ModularSitemap
{
    public class SitemapLoader : ISitemapLoader
    {
        #region ISitemapLoader Members
        [CLSCompliant(true)]
        public void LoadSiteMap(string file, ISiteMapBuilderService siteMapBuilderService, SiteMapNodeInfo parent, string module)
        {
            XmlDocument xmlDoc = new XmlDocument();
            string filePAth = HttpContext.Current.Server.MapPath(file);
            xmlDoc.Load(filePAth);

            if (xmlDoc.DocumentElement != null)
                foreach (XmlNode childNode in xmlDoc.DocumentElement.ChildNodes)
                {
                    AddSiteMapNodeRecursive(siteMapBuilderService, parent, childNode, module);
                }
        }

        #endregion

        #region Sitemap function

        private void AddSiteMapNodeRecursive(ISiteMapBuilderService siteMapBuilder, SiteMapNodeInfo parent, XmlNode xmlNode, string module)
        {
            string resourceKey = null;
            string url = null;
            string description = null;
            string key = null;
            string title = "";
            int rank = int.MaxValue;

            ArrayList roles = null;
            NameValueCollection attributes = new NameValueCollection();
            if (xmlNode.Attributes == null)
            {
                // Node without attributes, probably a comment
                return;
            }
            foreach (XmlAttribute att in xmlNode.Attributes)
            {
                string name = att.Name;

                if (name.Equals("roles"))
                {
                    string[] rolesArr = att.Value.Split();
                    if (rolesArr.Length > 0)
                    {
                        roles = new ArrayList();
                        foreach (string role in rolesArr)
                        {
                            roles.Add(role);
                        }
                    }
                }
                else if (name.Equals("resourceKey"))
                {
                    resourceKey = att.Value;
                }
                else if (name.Equals("url"))
                {
                    url = att.Value;
                }
                else if (name.Equals("rank"))
                {
                    int.TryParse(att.Value, out rank);
                }
                else if (name.Equals("title"))
                {
                    title = att.Value;
                }
                else if (name.Equals("shortcutKey"))
                {
                    attributes.Add("shortcutKey", att.Value);
                }
                else if (name.Equals("description"))
                {
                    description = att.Value;
                }
                else
                {
                    attributes.Add(att.Name, att.Value);
                }
            }

            if (resourceKey == null && url == null)
            {
                // Can't add node that has no resource key and no URL
                return;
            }

            if (resourceKey == null)
            {
                string prepareKey = url;

                prepareKey = Regex.Replace(prepareKey, "~/", "");
                prepareKey = Regex.Replace(prepareKey, ".aspx", "");
                prepareKey = Regex.Replace(prepareKey, "/", "_");
                resourceKey = prepareKey;
            }

            if (url != null)
            {
                if (url.Length > 1 && url[0] == '~')
                {
                    if (url[1] == '/' && HttpRuntime.AppDomainAppVirtualPath.EndsWith("/"))
                    {
                        url = HttpRuntime.AppDomainAppVirtualPath + url.Substring(2);
                    }
                    else
                    {
                        url = HttpRuntime.AppDomainAppVirtualPath + url.Substring(1);
                    }
                }
            }

            //string key = url == null ? resourceKey : url;
            if (!string.IsNullOrEmpty(module))
            {
                // append the module name to the front of the key, this way we sidestep 
                // some name conflicts my using a namespace like approach
                key = string.Format("{0}.{1}", module, resourceKey);
            }

            SiteMapNodeInfo siteMapNodeInfo = new SiteMapNodeInfo(key, url, resourceKey, description, roles, attributes, null, resourceKey);

            try
            {
                if (parent == null)
                {
                    if (rank != int.MaxValue)
                    {
                        siteMapBuilder.AddNode(siteMapNodeInfo, rank);
                    }
                    else
                        siteMapBuilder.AddNode(siteMapNodeInfo);
                }
                else
                {
                    if (rank != int.MaxValue)
                    {
                        siteMapBuilder.AddNode(siteMapNodeInfo, parent, rank);
                    }
                    else
                        siteMapBuilder.AddNode(siteMapNodeInfo, parent);
                }
            }
            catch (Exception ex)
            {
                // do something
                throw new Exception(string.Format("Error adding Sitemap Node {0} : {1}", key, ex.Message));
            }

            foreach (XmlNode childNode in xmlNode.ChildNodes)
            {
                AddSiteMapNodeRecursive(siteMapBuilder, siteMapNodeInfo, childNode, module);
            }

        }

        #endregion
    }
}
